/**
 *    业务机会变更阶段时检查客户必填字段
 *    created by Harry 2016-12-26 17:01:21
 *   
 */
public class OppStageChangeCheckNote implements Triggers.handler{
    public void handle(){

        List<Opportunity> oppList = (List<Opportunity>)Trigger.new;
        Map<Id,Opportunity> oldOppMap = (Map<Id,Opportunity>)Trigger.oldMap;
        
        Set<Id> oppIdSet = new Set<Id>();
        Set<Id> oppIdSet2 = new Set<Id>();
        Set<Id> oppIdSet3 = new Set<Id>();
        Set<Id> oppIdSet4 = new Set<Id>();

        Set<Id> accIdSet = new Set<Id>();
        Map<Id,Id> oppIdAccMap = new Map<Id,Id>();

       // Map<Id, RecordType> rtMap = new Map<Id, RecordType>([select Id, DeveloperName from RecordType where SobjectType = 'Opportunity']);
        

        //1. 筛选出符合条件的业务机会
        for(Opportunity opp:oppList){
            Opportunity oldOpp = oldOppMap.get(opp.Id);

            // System.debug(LoggingLevel.INFO, '*** opp.StageName: ' + opp.StageName);
            // System.debug(LoggingLevel.INFO, '*** oldOpp.StageName: ' + oldOpp.StageName);

            //终端客户业务机会
            if('CustomerOpportunity' == opp.RecordTypeName__c && opp.StageName!= '意向' && opp.StageName != '失败' && opp.StageName != oldOpp.StageName){
                oppIdSet.add(opp.Id);
            }
            //经销商业务机会
            /*if('DealerOpportunity' == opp.RecordTypeName__c && opp.StageName!= '意向' && opp.StageName != '失败' && opp.StageName != oldOpp.StageName){
               // oppIdSet2.add(opp.Id);
            }*/
            //
            /*if('市场沟通' == opp.StageName ){
                oppIdset3.add(opp.Id);
            }*/
            //终端客户业务机会 阶段变为立项时
            if('立项' == opp.StageName && 'CustomerOpportunity' == opp.RecordTypeName__c  && opp.StageName != oldOpp.StageName){
                oppIdset4.add(opp.Id);
                accIdSet.add(opp.AccountId);
                oppIdAccMap.put(opp.Id,opp.AccountId);
            }

        }
        System.debug(LoggingLevel.INFO, '*** oppIdSet: ' + oppIdSet);
        System.debug(LoggingLevel.INFO, '*** oppIdSet2: ' + oppIdSet2);
        System.debug(LoggingLevel.INFO, '*** oppIdSet3: ' + oppIdSet3);
        System.debug(LoggingLevel.INFO, '*** oppIdSet4: ' + oppIdSet4);
        System.debug(LoggingLevel.INFO, '*** accIdSet: ' + accIdSet);

        Map<Id,Opportunity> filterMap = null;
        Map<Id,Opportunity> filterMap2 = null;
        Map<Id,Opportunity> filterMap3 = null;
        Map<Id,Opportunity> filterMap4 = null;
        Map<Id,Account> filterMap5 = null;
        //2. 查询筛选
        if(oppIdSet.size()>0){
            filterMap = new Map<Id,Opportunity>(
                [SELECT Id,StageName,RecordType.DeveloperName,
                    Account.Phone,Account.Category__c,Account.Level__c,Account.CustomerAttribute__c,
                    Account.Province__c,Account.City__c,Account.District__c,Account.Address__c,
                    Account.Postcode__c,Account.BedNumOpen__c,Account.SpecialDepart__c,
                    Account.LastYearRevenue__c
                FROM Opportunity 
                WHERE Id IN : oppIdSet]);
        }

        /*if(oppIdSet2.size()>0){
            filterMap2 = new Map<Id,Opportunity>(
                [SELECT Id,StageName,RecordType.DeveloperName,
                    Account.CusType__c,Account.Artificial__c,Account.Phone,Account.Address__c,
                    Account.RegisterAmount__c,Account.Province__c,Account.City__c,Account.District__c,
                    Account.Postcode__c,Account.BusinessLicenseEndDate__c,Account.Company__c,
                    Account.LastYearRevenue__c,Account.Actual_Controller__c,Account.Master_Shareholder__c
                FROM Opportunity 
                WHERE Id IN : oppIdSet2]);
        }*/
        
       /* if(oppIdSet3.size()>0){
            filterMap3 = new Map<Id,Opportunity>(
                [SELECT Id, RecordType.DeveloperName,Country__c,
                (SELECT Id, Name FROM Attachments),
                (SELECT Id FROM CountryOpportunity__r)
                FROM Opportunity WHERE Id IN: oppIdSet3]);
        }*/

        if(oppIdSet4.size()>0){
            filterMap4 = new Map<Id,Opportunity>(
                [SELECT Id, RecordType.DeveloperName, AccountId,Department__c,
                (SELECT Id, Name FROM IntentPdtOpp__r )
                FROM Opportunity WHERE Id IN: oppIdset4]);
        }
        if(accIdSet.size()>0){
            filterMap5 = new Map<Id,Account>(
                [SELECT Id, Name, 
                (SELECT Id, Name, hospitalDepartments__c,LastYearRevenue__c,PurchasingCost__c FROM TerminalCustomer__r),
                (SELECT Id, Name, Post__c, Departments__c FROM  Contacts) 
                FROM Account WHERE Id IN: accIdSet]);
        }

        System.debug(LoggingLevel.INFO, '*** filterMap: ' + filterMap);
        System.debug(LoggingLevel.INFO, '*** filterMap2: ' + filterMap2);
        System.debug(LoggingLevel.INFO, '*** filterMap3: ' + filterMap3);
        System.debug(LoggingLevel.INFO, '*** filterMap4: ' + filterMap4);
        System.debug(LoggingLevel.INFO, '*** filterMap5: ' + filterMap5);


        //3. 添加报错信息
        Map<Id,String> errorMap = new Map<Id,String>();
        
        if(null != filterMap){
            //终端客户字段检查
            terminalFiledsCheck(filterMap,errorMap);
        }
       /* if(null != filterMap2){
            //经销商字段检查
            dealerFieldsCheck(filterMap2,errorMap);
        }*/
        /*if(null != filterMap3){
            //市场沟通前置条件检查
            marketCommCheck(filterMap3,errorMap);
        }*/
        if(null != filterMap4 && null!= filterMap5){
            //阶段变为立项时的前置条件检查
            lixiangCheck(filterMap4,filterMap5,oppIdAccMap,errorMap);
        }

        System.debug(LoggingLevel.INFO, '*** errorMap: ' + errorMap);

        for(Opportunity opp: oppList){
            if(null!=errorMap.get(opp.Id)){
                opp.addError('该业务机会不能变更阶段：</br>'+errorMap.get(opp.Id),false);
            }
        }
    }
    /**
     *    阶段变为立项时的前置条件检查
     */
    private static void lixiangCheck(Map<Id,Opportunity> filterMap4, Map<id,Account> filterMap5, Map<Id,Id> oppIdAccMap, Map<Id,String> errorMap){
        // addErrorLineIntoErrorMap(id,errorMap,'该业务机会不能变更阶段，请完善以下信息：')
        for(Id id : filterMap4.keySet()){
            Opportunity oppo = filterMap4.get(id);
            Id accId = oppIdAccMap.get(oppo.Id);
            Account acc = filterMap5.get(accId);

            //联系人前置条件检查
            List<Contact> contactList = acc.Contacts;
            String standardsStr = Label.Standard_OpportunityContact;
            List<String> srtList = standardsStr.split('、');
            //需要的联系人职务，后面发现存在一个就remove掉一个                
            Set<String> needPost = new Set<String>(srtList);
            removeExistPost(contactList,needPost);
            if(!needPost.isEmpty()){
                addErrorLineIntoErrorMap(id,errorMap,'客户缺少这些联系人：'+String.join(new List<String>(needPost),', '));
            }

            //意向产品前置条件检查
            if(oppo.IntentPdtOpp__r.isEmpty()){
                addErrorLineIntoErrorMap(id,errorMap,'请添加意向产品');
            }

            ////意向科室 上年采购额
            //意向科室前置条件检查
            if(null==oppo.Department__c||String.isBlank(oppo.Department__c)){
                addErrorLineIntoErrorMap(id,errorMap,'请选择意向科室');
            }else{
                //没有年收入的科室
                List<String> noIncomeDepts = new List<String>();
                //没有客户下对应科室的意向科室,初始化为全部值，后面若找到一个则remove掉一个
                Set<String> iDepts = new Set<String>();
                iDepts.addAll(oppo.Department__c.split(';'));
                Set<String> noDepts = new Set<String>(iDepts);
                ///没有上年采购额的科室
                Set<String> noPurchasingCostDpets = new Set<String>();
                //意向科室检查
                checkNotExistIntentDepts(acc,oppo,iDepts,noIncomeDepts,noDepts,noPurchasingCostDpets);

                if(!noIncomeDepts.isEmpty()){
                    addErrorLineIntoErrorMap(id,errorMap,'客户下的这些科室未填写【科室上年收入】！'+String.join(noIncomeDepts,', '));
                }
                if(!noPurchasingCostDpets.isEmpty()){
                    addErrorLineIntoErrorMap(id,errorMap,'客户下的这些科室未填写【科室上年采购额】！'+String.join(new List<String>(noPurchasingCostDpets),', '));
                }
                if(!noDepts.isEmpty()){
                    addErrorLineIntoErrorMap(id,errorMap,'该业务机会下的这些意向科室在客户中未找到：'+String.join(new List<String>(noDepts),', '));
                }
            }
        }
    }

    //市场沟通前置条件检查
   /* private static void marketCommCheck(Map<Id,Opportunity> filterMap3, Map<Id,String> errorMap){
        for(Id id : filterMap3.keySet()){
            Opportunity oppo = filterMap3.get(id);
            if(null == oppo.Attachments || !hasOpponent(oppo.Attachments)){
                addErrorLineIntoErrorMap(id,errorMap,'请以附件形式上传竞争对手价格信息！附件名必须包含[竞争对手价格]几个字');//业务机会还未满足"市场沟通"的条件，
            }
        }
    }*/

    /**
     *    若客户的科室中没有该意向科室，意向科室的名称会放到noDepts集合中，
     *    若客户的科室中有该意向科室，检查客户科室的年收入字段是否为空，
     *        若客户科室的年收入字段为空，改客户科室的名称会放到noIncomeDepts集合中。
     */
    private static void checkNotExistIntentDepts(Account acc, Opportunity oppo, Set<String> iDepts, List<String> noIncomeDepts, Set<String> noDepts,Set<String> noPurchasingCostDpets){
        // 意向科室选项列表值
        List<Department__c> depts = acc.TerminalCustomer__r;
        for(Department__c dept :depts){
            if(iDepts.contains(dept.hospitalDepartments__c)){
                if(null == dept.LastYearRevenue__c){
                    noIncomeDepts.add(dept.Name);
                }
                if(dept.PurchasingCost__c == null){
                    noPurchasingCostDpets.add(dept.Name);
                }
                noDepts.remove(dept.hospitalDepartments__c);
            }
        }
    }

    /**
     *    needPost进来时为所有必填职位，这个方法会将已存在的职位移出集合。
     *    方法结束时needPost剩下的为缺少的联系人职务
     */
    private static void removeExistPost(List<Contact> contactList,Set<String> needPost){
        for(Contact con : contactList){
            if(null==con.Post__c || String.isBlank(con.Post__c) ){
                continue;
            }
            if(con.Post__c.startsWith('院长')){
                needPost.remove(con.Post__c);
            }else if(con.Post__c.startsWith('分管院长')){
                needPost.remove('分管院长');
            }else if(con.Post__c.startsWith('科长/主任')){
                if(null!=con.Departments__c){
                    if(con.Departments__c.contains('检验科')){
                        needPost.remove('检验科长');
                    }else if(con.Departments__c.contains('设备科')||con.Departments__c.contains('采购科')){
                        needPost.remove('设备科长/采购科长');
                        // needPost.remove('采购科长');
                    }else if(con.Departments__c.contains('财务科')){
                        needPost.remove('财务科长');
                    }
                }
            }
        }
    }
    /**
     *    添加错误提示行 到错误提示缓存中，每行结束时带上</br>
     */
    private static void addErrorLineIntoErrorMap(Id oppId, Map<Id,String> errorMap, String errMsg){
        addErrorLineIntoErrorMap(oppId,errorMap,errMsg,'</br>');
    }
    /**
     *    添加错误提示行 到错误提示缓存中，每行结束时带上指定的字符endChar
     */
    private static void addErrorLineIntoErrorMap(Id oppId, Map<Id,String> errorMap, String errMsg, String endChar){
        String line = '';
        if(null!=errorMap.get(oppId)){
            line+=errorMap.get(oppId);
        }
        line+=errMsg+(endChar==null?'':endChar);
        errorMap.put(oppId,line);
    }

    /**
     *  附件中是否有竞争对手的价格
     
    private static boolean hasOpponent(List<Attachment> atm){
        for ( Attachment att : atm) {
            if(att.Name.contains('竞争对手价格')){
                return true;
            }                        
        }
        return false;
    }*/
    /**
     *    经销商字段检查
     */
   /* private static void dealerFieldsCheck(Map<Id,Opportunity> filterMap2,Map<Id,String> errorMap){
        for(Id id : filterMap2.keySet()){
            List<String> nullFieldList = new List<String>();
            Opportunity oppo = filterMap2.get(id);
            //企业类别 法定代表人 详细地址 电话 注册资金 省份 地级市 区县 邮政编码 营业执照到期日 关联公司 上年度总收入 主要股东 实际控制人
        
            if(String.isBlank(oppo.Account.Artificial__c)){
                nullFieldList.add('法定代表人');
            }
            if(String.isBlank(oppo.Account.Phone)){
                nullFieldList.add('电话');
            }
            if(String.isBlank(oppo.Account.Address__c)){
                nullFieldList.add('详细地址');
            }
            if(null==oppo.Account.RegisterAmount__c){
                nullFieldList.add('注册资金');
            }
            if(String.isBlank(oppo.Account.Province__c)){
                nullFieldList.add('省份');
            }
            if(String.isBlank(oppo.Account.City__c)){
                nullFieldList.add('地级市');
            }
            if(String.isBlank(oppo.Account.District__c)){
                nullFieldList.add('区县');
            }
            if(String.isBlank(oppo.Account.Postcode__c)){
                nullFieldList.add('邮政编码');
            }
           
            if(String.isBlank(oppo.Account.Company__c)){
                nullFieldList.add('关联公司');
            }
            if(null==oppo.Account.LastYearRevenue__c){
                nullFieldList.add('上年度总收入');
            }
            if(String.isBlank(oppo.Account.Actual_Controller__c)){
                nullFieldList.add('主要股东');
            }
            if(String.isBlank(oppo.Account.Master_Shareholder__c)){
                nullFieldList.add('实际控制人');
            }
            if(!nullFieldList.isEmpty()){
                addErrorLineIntoErrorMap(id,errorMap,'请先维护客户中的以下信息：' + String.join(nullFieldList, ', ') );
            }
        }
    }*/
    /**
     *    终端客户字段检查
     *    为业务机会变更状态时 添加必填字段的检查 
     *    返回一个未填字段的集合
     */
    private static void terminalFiledsCheck(Map<Id,Opportunity> filterMap,Map<Id,String> errorMap){
        for(Id id: filterMap.keySet()){
            List<String> nullFieldList = new List<String>();
            Opportunity oppo = filterMap.get(id);
            //'电话' '客户类别' '客户等级' '客户属性' '省份' '地级市' '区县' '详细地址' '邮政编码' '编制床位数' '特色科室' '上年度总收入'
            if(String.isBlank(oppo.Account.Phone)){
                nullFieldList.add('电话');
            }
            if(String.isBlank(oppo.Account.Category__c)){
                nullFieldList.add('客户类别');
            }
            if(String.isBlank(oppo.Account.Level__c)){
                nullFieldList.add('客户等级');
            }
            if(String.isBlank(oppo.Account.CustomerAttribute__c)){
                nullFieldList.add('客户属性');
            }
            if(String.isBlank(oppo.Account.Province__c)){
                nullFieldList.add('省份');
            }
            if(String.isBlank(oppo.Account.City__c)){
                nullFieldList.add('地级市');
            }
            if(String.isBlank(oppo.Account.District__c)){
                nullFieldList.add('区县');
            }
            if(String.isBlank(oppo.Account.Address__c)){
                nullFieldList.add('详细地址');
            }
            /*if(String.isBlank(oppo.Account.Postcode__c)){
                nullFieldList.add('邮政编码');
            }*/
            if(null==oppo.Account.BedNumOpen__c){
                nullFieldList.add('开放床位数');
            }
            if(String.isBlank(oppo.Account.SpecialDepart__c)){
                nullFieldList.add('特色科室');
            }
            if(null==oppo.Account.LastYearRevenue__c){
                nullFieldList.add('上年度总收入');
            }
            if(!nullFieldList.isEmpty()){
                addErrorLineIntoErrorMap(id,errorMap,'请先维护客户中的以下信息：' + String.join(nullFieldList, ', ') );
            }
        }
    }
}